/*
 * userStockboy.h
 *
 *  Created on: Jun 16, 2011
 *      Author: peckb1
 */

#ifndef USERSTOCKBOY_H_
#define USERSTOCKBOY_H_

#include "userSharedDefinitions.h"
#include "syscall.h"
#include "userHomedepot.h"
#include "userLocks.h"


typedef struct StockBoy {
    int _stockBoyIndex;
} StockBoy;



void StockBoyDoWork(int stockBoyId) {
	int stockBoysBreakLock;
	int i;
	int customersWaiting;
	int questionLock;
	int answerLock;
	int stockBoysStatus;
	int itemIDQuestioned;
	int customerIDasking;
	int aisleIDAns;
	int stockRoomLock;
	int justWokeup;
	int itemIdToBeReStocked;
	int reStockLock;
	int currentAisleIndex;
	int itemLock;
	int aisleID;
	StockBoy stockboy;
    /* stockboy = getStockboy(stockBoyId); */
    stockboy._stockBoyIndex = stockBoyId;
    /* We are currently unavailable */
    Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
    theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
    Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

    stockRoomLock = theLocksInHomeDepotEntry._stockRoomLock;
    justWokeup = TRUE;

    while(TRUE == TRUE) {
        /* lets see if we need to re stock an item */
        /* _theLocksInHomeDepotEntry._stockBoyOrderLock->Acquire(); */
        itemIdToBeReStocked = NOT_FOUND;

        /* _stockBoyReStockingItem */
        #ifdef PRINT_EXTRA_LOG_STOCKBOY
            printf_3("StockBoy #", stockBoyId, " lets see if any body needs restocking.\n");
        #endif

        reStockLock = theLocksInHomeDepotEntry._customerWaitingForReStockLock;

        #ifdef PRINT_LOCKS_STOCKBOY
            printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire()\n");
        #endif

        Acquire(reStockLock);

        #ifdef PRINT_LOCKS_STOCKBOY
            printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire() Done!\n");
        #endif

        for (i=0; i< MAX_ITEMS; i++) {
            if (theLocksInHomeDepotEntry._customersWaitingForRestock[i] > 0 && theLocksInHomeDepotEntry._stockBoyReStockingItem[i] == NOT_FOUND) {
                itemIdToBeReStocked = i;
                theLocksInHomeDepotEntry._stockBoyReStockingItem[i] = stockBoyId;
                break;
            }
        }

        #ifdef PRINT_LOCKS_STOCKBOY
            printf_3("StockBoy #", stockBoyId, " reStockLock->Release()\n");
        #endif

        Release(reStockLock);

        #ifdef PRINT_LOCKS_STOCKBOY
            printf_3("StockBoy #", stockBoyId, " reStockLock->Release() Done!\n");
        #endif

        if (itemIdToBeReStocked != NOT_FOUND) {
            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " finds out item#", itemIdToBeReStocked, " needs to be re stock\n");
            #endif

            if (justWokeup == FALSE) {
                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_5("StockBoy [", stockBoyId, "] goes back to Stock room for item [", itemIdToBeReStocked, "]\n");
                #endif
            }

            /* i need to re stock, lets acquire the storage room */
            Acquire(theLocksInHomeDepotEntry._stockRoomStatusLock);

            while (theLocksInHomeDepotEntry._stockBoyIdInStockRoom != NOT_FOUND) {
                theLocksInHomeDepotEntry._stockBoysWaitingForStockRoomCV ++;

                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_5("StockBoy [", stockBoyId, "] is waiting for StockBoy [", theLocksInHomeDepotEntry._stockBoyIdInStockRoom, "] to leave the Stock Room.\n");
                #endif

                Wait(theLocksInHomeDepotEntry._stockRoomCV, theLocksInHomeDepotEntry._stockRoomStatusLock);
            }

            #ifdef PRINT_OUTPUT_STOCKBOY
                printf_3("StockBoy [", stockBoyId, "] is in stock room\n");
            #endif

            theLocksInHomeDepotEntry._stockBoyIdInStockRoom = stockBoyId;
            Release(theLocksInHomeDepotEntry._stockRoomStatusLock);

            /* Now we are at stock room, we grab supplies and will get out of the room */
            /* so other stock boys can use it, */

            /* PickupSuppliesFromStorage(stockboy, itemIdToBeReStocked); */

                /* We already have acquired the lock for storage */
                /* in previous. Section. No additional code required in here because we know we can */
                /* pick up as many as required. */
                for (i = 1; i< 10; i++) {
                    Yield();
                }
                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_5("StockBoy [", stockBoyId, "] retrieves one new item [", itemIdToBeReStocked, "] from stock room.\n");
                #endif


            /*
             * Before leaving stock room we have to tell other stock boys that the next one can enter the stock room
             */

            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " is going to tell everyone he is leaving\n");
            #endif

            Acquire(theLocksInHomeDepotEntry._stockRoomStatusLock);
            theLocksInHomeDepotEntry._stockBoyIdInStockRoom = NOT_FOUND;

            if (theLocksInHomeDepotEntry._stockBoysWaitingForStockRoomCV > 0) {
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " find outs people are waiting for him, signal them to come in.\n");
                #endif

                theLocksInHomeDepotEntry._stockBoysWaitingForStockRoomCV --;
                Signal(theLocksInHomeDepotEntry._stockRoomCV, theLocksInHomeDepotEntry._stockRoomStatusLock);
            }

            #ifdef PRINT_OUTPUT_STOCKBOY
                printf_3("StockBoy [", stockBoyId, "] leaves stock room\n");
            #endif

            Release(theLocksInHomeDepotEntry._stockRoomStatusLock);

            /* By now we have got the supplies from stock room, locked the item, and can re stock it */
            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " is querying the aisle of item#", itemIdToBeReStocked, "\n");
            #endif

            /* currentAisleIndex = GetAisleNumber(getStoreInstance(), itemIdToBeReStocked); */
            currentAisleIndex = theLocksInHomeDepotEntry.itemsInStore[itemIdToBeReStocked]._aisle;

            /* ASSERT(currentAisleIndex >= 0 && currentAisleIndex < MAX_AISLES); */
            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_7("StockBoy #", stockBoyId, " found out the aisle#", currentAisleIndex, " of item#", itemIdToBeReStocked, "\n");
            #endif

            /* Lets go to its aisle. Set Status to current aisle */
            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " Set stock boy status()\n");
            #endif

            /* SetStockBoysStatus(stockboy, stockBoyId, currentAisleIndex); */
            Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
            theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = currentAisleIndex;
            Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " Set stock boy status() Done!\n");
            #endif
            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " is in the aisle#", currentAisleIndex, "\n");
            #endif

            /* but first we need to lock the item */
            /* so no other stock boy or customer can manipulate its values while we are */
            /* re stocking it. */
            itemLock  = theLocksInHomeDepotEntry._shelfLock[itemIdToBeReStocked];

            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " needs to lock the item#", itemIdToBeReStocked, " first in order to restock it\n");
            #endif
            #ifdef PRINT_LOCKS_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Lock()\n");
            #endif

            Acquire(itemLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Lock()\n");
            #endif

            /* Re stock the item */
            /* RestockItem(getStoreInstance(), itemIdToBeReStocked); */
            theLocksInHomeDepotEntry.itemsInStore[itemIdToBeReStocked]._quantity ++;

            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " ReStcoked the item# ", itemIdToBeReStocked, "\n");
                /* let the waiting customers know that the item is available */
                printf_5("StockBoy #", stockBoyId, " lets wake up people who are waiting for this item#", itemIdToBeReStocked, "\n");
            #endif
            #ifdef PRINT_LOCKS_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Release()\n");
            #endif

            Release(itemLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Release() Done!\n");
            #endif
            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire()\n");
            #endif

            Acquire(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire() Done!\n");
            #endif

            if (theLocksInHomeDepotEntry._customersWaitingForRestock[itemIdToBeReStocked] > 0) {
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " Currently ", theLocksInHomeDepotEntry._customersWaitingForRestock[itemIdToBeReStocked], " customers are waiting for this item. Signal one of them.\n");
                #endif

                theLocksInHomeDepotEntry._customersWaitingForRestock[itemIdToBeReStocked]--;

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " itemWaitCV[", itemIdToBeReStocked, "]->Signal()\n");
                #endif

                Signal(theLocksInHomeDepotEntry._itemWaitCV[itemIdToBeReStocked], reStockLock);
            }

            theLocksInHomeDepotEntry._stockBoyReStockingItem[itemIdToBeReStocked] = NOT_FOUND;

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Release()\n");
            #endif

            Release(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Release() Done!\n");
            #endif

            /* _theLocksInHomeDepotEntry._stockBoyOrderLock->Release(); */
            /* We are walking in aisle; yield to the coming customers */
            /* so they have an opportunity to ask their questions. */
            for (i = 0; i < STOCKBOY_DELAY; i++) {
                Yield();
            }

            /* OK. we have re-stocked an item, lets see if there are any customers in this */
            /* aisle who need help. */
            /* lets see if any customer has any question in current aisle. */
            /* AnswerQuestionsOfCustomers(stockboy, currentAisleIndex); */

                aisleID = currentAisleIndex;
                customersWaiting = theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionLock[aisleID];
                questionLock = theLocksInHomeDepotEntry._customerItemQuestionLock[stockBoyId];
                answerLock = theLocksInHomeDepotEntry._stockBoyAisleAnswerLock[stockBoyId];
                stockBoysStatus = theLocksInHomeDepotEntry._stockBoysStatusLock;

                /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] lets see if any body has any questions\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire()\n");
                #endif

                Acquire(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire() Done!\n");
                #endif

                if(theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                   theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                    while (theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] finds out there are ", theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                        #endif
                        /* There is a customer needing help */
                        /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                        /* _theLocksInHomeDepotEntry.SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                        (theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID])--;
                        /* Now the customer can ask his/her question. */
                        /* Lets wait to receive the Item Number */

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release()\n");
                        #endif

                        Release(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n");
                        #endif

                        Wait(theLocksInHomeDepotEntry._customerItemQuestionCV[stockBoyId], questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n Done!");
                        #endif

                        itemIDQuestioned = theLocksInHomeDepotEntry._customerItemQuestionMV[stockBoyId];
                        customerIDasking = theLocksInHomeDepotEntry._customerID_AskingQuestionMV[stockBoyId];

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                        #endif
                        /* Lets answer the question asked */
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release() Done\n");
                        #endif

                        /* aisleIDAns = GetAisleNumber(getStoreInstance(), itemIDQuestioned); */

                        aisleIDAns = theLocksInHomeDepotEntry.itemsInStore[itemIDQuestioned]._aisle;


                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                        #endif

                        theLocksInHomeDepotEntry._stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._stockBoyAisleAnswerCV[stockBoyId], answerLock);

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire()\n");
                        #endif

                        Acquire(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release Done!()\n");
                        #endif
                    }
                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                }

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release()\n");
                #endif

                Release(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] stockBoyStatus->Acquire()\n");
                #endif

                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);


            /* lets see if any customer has any question in service area. */
            /* AnswerQuestionsOfCustomers(stockboy, SERVICE_AREA_LINE); */

                aisleID = SERVICE_AREA_LINE;
                customersWaiting = theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionLock[aisleID];
                questionLock = theLocksInHomeDepotEntry._customerItemQuestionLock[stockBoyId];
                answerLock = theLocksInHomeDepotEntry._stockBoyAisleAnswerLock[stockBoyId];
                stockBoysStatus = theLocksInHomeDepotEntry._stockBoysStatusLock;

                /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] lets see if any body has any questions\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire()\n");
                #endif

                Acquire(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire() Done!\n");
                #endif

                if(theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                   theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                    while (theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] finds out there are ", theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                        #endif
                        /* There is a customer needing help */
                        /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                        /* _theLocksInHomeDepotEntry.SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                        theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID]--;
                        /* Now the customer can ask his/her question. */
                        /* Lets wait to receive the Item Number */

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release()\n");
                        #endif

                        Release(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n");
                        #endif

                        Wait(theLocksInHomeDepotEntry._customerItemQuestionCV[stockBoyId], questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n Done!");
                        #endif

                        itemIDQuestioned = theLocksInHomeDepotEntry._customerItemQuestionMV[stockBoyId];
                        customerIDasking = theLocksInHomeDepotEntry._customerID_AskingQuestionMV[stockBoyId];

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                        #endif
                        /* Lets answer the question asked */
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release() Done\n");
                        #endif

                        /* aisleIDAns = GetAisleNumber(getStoreInstance(), itemIDQuestioned); */
                        {
                            aisleIDAns = theLocksInHomeDepotEntry.itemsInStore[itemIDQuestioned]._aisle;
                        }

                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                        #endif

                        theLocksInHomeDepotEntry._stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._stockBoyAisleAnswerCV[stockBoyId], answerLock);

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire()\n");
                        #endif

                        Acquire(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release Done!()\n");
                        #endif
                    }
                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                }

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release()\n");
                #endif

                Release(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] stockBoyStatus->Acquire()\n");
                #endif

                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);


            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_3("StockBoy #[", stockBoyId, "] is back from service\n");
            #endif

            justWokeup = FALSE;
        } else {
            /* before we go on break, lets see if any customer has any question waiting in service area. */
            /* AnswerQuestionsOfCustomers(stockboy, SERVICE_AREA_LINE); */

                aisleID = SERVICE_AREA_LINE;
                customersWaiting = theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionLock[aisleID];
                questionLock = theLocksInHomeDepotEntry._customerItemQuestionLock[stockBoyId];
                answerLock = theLocksInHomeDepotEntry._stockBoyAisleAnswerLock[stockBoyId];
                stockBoysStatus = theLocksInHomeDepotEntry._stockBoysStatusLock;

                /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] lets see if any body has any questions\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire()\n");
                #endif

                Acquire(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customersWaiting->Acquire() Done!\n");
                #endif

                if(theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                   theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                    while (theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] finds out there are ", theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                        #endif
                        /* There is a customer needing help */
                        /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                        /* _theLocksInHomeDepotEntry.SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                        theLocksInHomeDepotEntry._customersWaitingInAisleToAskQuestionMV[aisleID]--;
                        /* Now the customer can ask his/her question. */
                        /* Lets wait to receive the Item Number */

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release()\n");
                        #endif

                        Release(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customersWaiting->Release() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n");
                        #endif

                        Wait(theLocksInHomeDepotEntry._customerItemQuestionCV[stockBoyId], questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Wait()\n Done!");
                        #endif

                        itemIDQuestioned = theLocksInHomeDepotEntry._customerItemQuestionMV[stockBoyId];
                        customerIDasking = theLocksInHomeDepotEntry._customerID_AskingQuestionMV[stockBoyId];

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                        #endif
                        /* Lets answer the question asked */
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire()\n");
                        #endif

                        Acquire(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] Answer[", stockBoyId, "]->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(questionLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] question[", stockBoyId, "]->Release() Done\n");
                        #endif

                        /* aisleIDAns = GetAisleNumber(getStoreInstance(), itemIDQuestioned); */
                        {
                            aisleIDAns = theLocksInHomeDepotEntry.itemsInStore[itemIDQuestioned]._aisle;
                        }

                        #ifdef PRINT_EXTRA_LOG_STOCKBOY
                            printf_7("StockBoy [", stockBoyId, "] the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                        #endif

                        theLocksInHomeDepotEntry._stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                        #endif

                        Signal(theLocksInHomeDepotEntry._stockBoyAisleAnswerCV[stockBoyId], answerLock);

                        #ifdef PRINT_OUTPUT_STOCKBOY
                            printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire()\n");
                        #endif

                        Acquire(customersWaiting);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_3("StockBoy [", stockBoyId, "] customerWaiting->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release()\n");
                        #endif

                        Release(answerLock);

                        #ifdef PRINT_LOCKS_STOCKBOY
                            printf_5("StockBoy [", stockBoyId, "] answer[", stockBoyId, "]->Release Done!()\n");
                        #endif
                    }
                    theLocksInHomeDepotEntry._stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                }

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release()\n");
                #endif

                Release(customersWaiting);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] customerWaiting->Release() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] stockBoyStatus->Acquire()\n");
                #endif

                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);


            /* GoToBreak(stockboy); */

                /* We are currently unavailable */
                /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                Acquire(theLocksInHomeDepotEntry._stockBoysStatusLock);
                theLocksInHomeDepotEntry._stockBoysStatus[stockBoyId] = -1;
                Release(theLocksInHomeDepotEntry._stockBoysStatusLock);

                stockBoysBreakLock = theLocksInHomeDepotEntry._stockBoyBreakLock;
                Acquire(stockBoysBreakLock);
                theLocksInHomeDepotEntry._stockBoyOnBreakMV++;

                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] is going on break.\n");
                #endif

                Wait(theLocksInHomeDepotEntry._stockBoysOnBreakCV, stockBoysBreakLock);

                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] got call from Manager.\n");
                #endif

                Release(stockBoysBreakLock);


            justWokeup = TRUE;
        }
    }
}

#endif /* USERSTOCKBOY_H_ */
